package com.vip.seata.at.order.util.feign;
/**
 * Description :
 *
 * @Author Evan Liu
 * @Date 2019年4月24日
 */
/*
 * Copyright 2012-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import com.alibaba.fastjson.JSON;
import com.vip.seata.at.order.util.ApplicationHelper;
import com.vip.seata.at.order.util.SleuthHelper;
import com.vip.seata.at.order.util.StringPool;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * 拦截所有的 HttpHeader(RPC-Mode=RPC-Mode-HTTP)进行日志日志记录
 * @author liuwei
 */
@Slf4j
@Component
@ConditionalOnProperty(value = "feign.traceable.enabled",havingValue = "true",matchIfMissing = false)
public class FeignTraceFilter extends OncePerRequestFilter implements Ordered {

    @Setter
    private int order = Ordered.LOWEST_PRECEDENCE - 10;

    @Override
    public int getOrder() {
        return this.order;
    }

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        log.info("Sleuth:{}",SleuthHelper.getSleuthTraceId());
        Map<String, String> headers = getHeaders(request);
        log.info("Headers:{}", JSON.toJSONString(headers));
        String mode = SleuthHelper.getBaggageValue(StringPool.RPC_Mode);
        if(!StringUtils.equalsIgnoreCase(mode,StringPool.RPC_Mode_Http)){
            filterChain.doFilter(request, response);
            return;
        }
        String origin = SleuthHelper.getBaggageValue(StringPool.RPC_Origin_Application);
        String referer = SleuthHelper.getBaggageValue(StringPool.RPC_Referer_Application);
        String application = ApplicationHelper.getApplicationName();
        String method = StringPool.EMPTY;
        String uri = request.getRequestURI();
        try {
            HandlerExecutionChain chain = handlerMapping.getHandler(request);
            if(chain != null) {
                Object handler = chain.getHandler();
                if(handler instanceof HandlerMethod){
                    HandlerMethod handlerMethod = (HandlerMethod) handler;
                    String message = StringUtils.substringBefore(handlerMethod.getShortLogMessage(),"[");
                    method = message;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        log.info("RPC-Mode-HTTP||origin:{} referer:{} target:{} method:{} uri:{}",origin,referer,application,method,uri);
        filterChain.doFilter(request, response);
    }

    private Map<String, String> getHeaders(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        if (enumeration != null) {
            while (enumeration.hasMoreElements()) {
                String key = enumeration.nextElement();
                String value = request.getHeader(key);
                map.put(key, value);
            }
        }
        return map;
    }
}


